package com.brokendust.client.api.module.text;

import com.brokendust.client.PixelEngine;
import com.brokendust.client.api.module.GUIComponent;
import com.brokendust.client.api.module.PullPanelComponent;
import com.brokendust.client.api.util.BasePosition;
import com.brokendust.client.api.util.NumberUtil;
import com.brokendust.client.config.module.ComponentJson;
import com.brokendust.client.config.module.text.TextLabelJson;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Multimap;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.platform.GlStateManager;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.AbstractGui;
import net.minecraft.util.text.ITextProperties;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.opengl.GL11;

import java.util.List;

@OnlyIn(Dist.CLIENT)
public class TextLabel extends AbstractGui implements GUIComponent, PullPanelComponent {
    public int guiWidth;
    public int guiHeight;
    public int guiDWidth;
    public int guiDHeight;
    public float scale;
    public int objectWidth;
    public int objectHeight;
    public int x;
    public int y;
    public int position;
    public boolean vertical;
    public int row_height;
    public int line_spacing;
    public int align;
    public List<String> text_list;
    public Multimap<String, Integer> text_size_map;
    public String object_id;
    int fontSize;
    int row;

    public TextLabel(TextLabelJson textLabelJson, int gui_weight, int gui_height, int guiDWidth, int guiDHeight) {
        this.text_size_map = LinkedListMultimap.create();
        this.row = 0;
        this.guiWidth = gui_weight;
        this.guiHeight = gui_height;
        this.guiDWidth = guiDWidth;
        this.guiDHeight = guiDHeight;
        this.scale = textLabelJson.getScale();
        this.object_id = textLabelJson.getObject_name();
        this.x = textLabelJson.getX();
        this.y = textLabelJson.getY();
        this.position = textLabelJson.getPosition();
        this.vertical = textLabelJson.isVertical();
        this.text_list = textLabelJson.getText_list();
        this.row_height = textLabelJson.getRow_height();
        this.line_spacing = textLabelJson.getLine_spacing();
        this.align = textLabelJson.getAlign();
        if (this.vertical) {
            this.fontSize = 0;
            for (String text : this.text_list) {
                int fLength = NumberUtil.stringLength(text);
                if (fLength > this.fontSize) {
                    this.fontSize = fLength;
                    this.objectHeight = (int) (fLength * this.scale);
                }
                this.text_size_map.put(text, fLength);
            }
            this.objectWidth = this.row_height * this.text_list.size();
        } else {
            this.fontSize = 0;
            for (String text : this.text_list) {
                int fLength = NumberUtil.stringLength(text);
                if (fLength > this.fontSize) {
                    this.fontSize = fLength;
                    this.objectWidth = (int) (fLength * this.scale);
                }
                this.text_size_map.put(text, fLength);
            }
            this.objectHeight = this.row_height * this.text_list.size();
        }
    }

    public TextLabel(TextLabelJson textLabelJson) {
        this.text_size_map = LinkedListMultimap.create();
        this.row = 0;
        this.scale = textLabelJson.getScale();
        this.object_id = textLabelJson.getObject_name();
        this.x = textLabelJson.getX();
        this.y = textLabelJson.getY();
        this.position = textLabelJson.getPosition();
        this.vertical = textLabelJson.isVertical();
        this.text_list = textLabelJson.getText_list();
        this.row_height = textLabelJson.getRow_height();
        this.line_spacing = textLabelJson.getLine_spacing();
        this.align = textLabelJson.getAlign();
        if (this.vertical) {
            this.fontSize = 0;
            for (String text : this.text_list) {
                int fLength = NumberUtil.stringLength(text);
                if (fLength > this.fontSize) {
                    this.fontSize = fLength;
                    this.objectHeight = (int) (fLength * this.scale);
                }
                this.text_size_map.put(text, fLength);
            }
            this.objectWidth = this.row_height * this.text_list.size();
        } else {
            this.fontSize = 0;
            for (String text : this.text_list) {
                int fLength = NumberUtil.stringLength(text);
                if (fLength > this.fontSize) {
                    this.fontSize = fLength;
                    this.objectWidth = (int) (fLength * this.scale);
                }
                this.text_size_map.put(text, fLength);
            }
            this.objectHeight = (int) (this.text_list.size() * 8 * this.scale);
        }
    }

    @Override
    public void upData(ComponentJson componentJson) {
        if (!(componentJson instanceof TextLabelJson)) {
            return;
        }
        TextLabelJson textLabelJson = (TextLabelJson) componentJson;
        this.scale = textLabelJson.getScale();
        this.position = textLabelJson.getPosition();
        this.vertical = textLabelJson.isVertical();
        this.text_list = textLabelJson.getText_list();
        this.row_height = textLabelJson.getRow_height();
        this.line_spacing = textLabelJson.getLine_spacing();
        this.align = textLabelJson.getAlign();
        this.text_size_map.clear();
        if (this.vertical) {
            this.fontSize = 0;
            for (String text : this.text_list) {
                int fLength = NumberUtil.stringLength(text);
                if (fLength > this.fontSize) {
                    this.fontSize = fLength;
                    this.objectHeight = (int) (fLength * this.scale);
                }
                this.text_size_map.put(text, fLength);
            }
            this.objectWidth = this.row_height * this.text_list.size();
        } else {
            this.fontSize = 0;
            for (String text : this.text_list) {
                int fLength = NumberUtil.stringLength(text);
                if (fLength > this.fontSize) {
                    this.fontSize = fLength;
                    this.objectWidth = (int) (fLength * this.scale);
                }
                this.text_size_map.put(text, fLength);
            }
            this.objectHeight = this.row_height * this.text_list.size();
        }
    }

    @Override
    public void renderGUI(MatrixStack matrixStack, int mouseX, int mouseY, float particleTick, int guiX, int guiY) {
        Integer[] integers = BasePosition.getObjectPoint(guiX, guiY, this.guiWidth, this.guiHeight, this.objectWidth, this.objectHeight, this.x, this.y, this.position);
        int mX = integers[0];
        int mY = integers[1];
        GlStateManager._pushMatrix();
        GlStateManager._scalef(this.scale, this.scale, this.scale);
        int mmX = Math.round(mX / this.scale);
        int mmY = Math.round(mY / this.scale);
        this.text_size_map.forEach((text, size) -> {
            int ss = this.fontSize - size;
            int sss = (this.fontSize - size) / 2;
            if (this.vertical) {
                if (this.align == 1) {
                    PixelEngine.fontRenderer.drawWordWrap(ITextProperties.of(text), mmX + this.row * this.row_height, mmY, 0, 15402245);
                }
                if (this.align == 2) {
                    PixelEngine.fontRenderer.drawWordWrap(ITextProperties.of(text), mmX + this.row * this.row_height, mmY + sss, 0, 15402245);
                }
                if (this.align == 3) {
                    PixelEngine.fontRenderer.drawWordWrap(ITextProperties.of(text), mmX + this.row * this.row_height, mmY + ss, 0, 15402245);
                }
            } else {
                if (this.align == 1) {
                    PixelEngine.fontRenderer.draw(matrixStack, text, (float) mmX, (float) (mmY + this.row * this.row_height), 15402245);
                }
                if (this.align == 2) {
                    PixelEngine.fontRenderer.draw(matrixStack, text, (float) (mmX + sss), (float) (mmY + this.row * this.row_height), 15402245);
                }
                if (this.align == 3) {
                    PixelEngine.fontRenderer.draw(matrixStack, text, (float) (mmX + ss), (float) (mmY + this.row * this.row_height), 15402245);
                }
            }
            ++this.row;
        });
        this.row = 0;
        GlStateManager._popMatrix();
    }

    @Override
    public void renderPull(MatrixStack matrixStack, int mouseX, int mouseY, float particleTick, int guiX, int guiY, int displayX, int displayY) {
        Integer[] integers = BasePosition.getObjectPoint(guiX, guiY, this.guiWidth, this.guiHeight, this.objectWidth, this.objectHeight, this.x, this.y, this.position);
        int mX = integers[0];
        int mY = integers[1];
        GlStateManager._pushMatrix();
        GlStateManager._scalef(this.scale, this.scale, this.scale);
        int mmX = Math.round(mX / this.scale);
        int mmY = Math.round(mY / this.scale);
        double scale = Minecraft.getInstance().getWindow().getGuiScale();
        GlStateManager._blendFuncSeparate((int) (displayX * scale), (int) (displayY * scale), (int) (this.guiDWidth * scale), (int) (this.guiDHeight * scale));
        GL11.glEnable(3089);
        this.text_size_map.forEach((text, size) -> {
            int ss = this.fontSize - size;
            int sss = (this.fontSize - size) / 2;
            if (this.vertical) {
                if (this.align == 1) {
                    PixelEngine.fontRenderer.drawWordWrap(ITextProperties.of(text), mmX + this.row * this.row_height, mmY, 0, 15402245);
                }
                if (this.align == 2) {
                    PixelEngine.fontRenderer.drawWordWrap(ITextProperties.of(text), mmX + this.row * this.row_height, mmY + sss, 0, 15402245);
                }
                if (this.align == 3) {
                    PixelEngine.fontRenderer.drawWordWrap(ITextProperties.of(text), mmX + this.row * this.row_height, mmY + ss, 0, 15402245);
                }
            } else {
                if (this.align == 1) {
                    PixelEngine.fontRenderer.draw(matrixStack, text, (float) mmX, (float) (mmY + this.row * this.row_height), 15402245);
                }
                if (this.align == 2) {
                    PixelEngine.fontRenderer.draw(matrixStack, text, (float) (mmX + sss), (float) (mmY + this.row * this.row_height), 15402245);
                }
                if (this.align == 3) {
                    PixelEngine.fontRenderer.draw(matrixStack, text, (float) (mmX + ss), (float) (mmY + this.row * this.row_height), 15402245);
                }
            }
            ++this.row;
        });
        this.row = 0;
        GL11.glDisable(3089);
        GlStateManager._popMatrix();
    }

    public void renderHUD(MatrixStack matrixStack, int window_width, int window_height) {
        Integer[] integers = BasePosition.getObjectHubPoint(window_width, window_height, this.objectWidth, this.objectHeight, this.x, this.y, this.position);
        int mX = integers[0];
        int mY = integers[1];
        GlStateManager._pushMatrix();
        float mScale = (float) Math.pow(this.scale, -1.0);
        GlStateManager._scalef(this.scale, this.scale, this.scale);
        int mmX = Math.round(mX / this.scale);
        int mmY = Math.round(mY / this.scale);
        this.text_size_map.forEach((text, size) -> {
            int ss = this.fontSize - size;
            int sss = ss / 2;
            if (this.vertical) {
                if (this.align == 1) {
                    PixelEngine.fontRenderer.drawWordWrap(ITextProperties.of(text), mmX + this.row * this.row_height, mmY, 0, 15402245);
                }
                if (this.align == 2) {
                    PixelEngine.fontRenderer.drawWordWrap(ITextProperties.of(text), mmX + this.row * this.row_height, mmY + sss, 0, 15402245);
                }
                if (this.align == 3) {
                    PixelEngine.fontRenderer.drawWordWrap(ITextProperties.of(text), mmX + this.row * this.row_height, mmY + ss, 0, 15402245);
                }
            } else {
                if (this.align == 1) {
                    PixelEngine.fontRenderer.draw(matrixStack, text, (float) mmX, (float) (mmY + this.row * this.row_height), 15402245);
                }
                if (this.align == 2) {
                    PixelEngine.fontRenderer.draw(matrixStack, text, (float) (mmX + sss), (float) (mmY + this.row * this.row_height), 15402245);
                }
                if (this.align == 3) {
                    PixelEngine.fontRenderer.draw(matrixStack, text, (float) (mmX + ss), (float) (mmY + this.row * this.row_height), 15402245);
                }
            }
            ++this.row;
        });
        this.row = 0;
        GlStateManager._scalef(mScale, mScale, mScale);
        GlStateManager._popMatrix();
        GL11.glPushMatrix();
        GL11.glScalef(this.scale, this.scale, this.scale);
        GL11.glPopMatrix();
    }
}
